import * as _ from "lodash"
import { camelCase, snakeCase } from "../case"
import { PageList } from "../data"
import httpClient from "../httpclient"

export enum CouponType {
  FixedDiscount = "fixed_discount",
  PercentageDiscount = "percentage_discount",
  RandomDiscount = "random_discount",
  ShippingDiscount = "shipping_discount",
  FreeShipping = "free_shipping",
}

export enum CouponStatus {
  Pending = "pending",
  Issuing = "issuing",
  Finished = "finished",
  Paused = "paused",
  Expired = "expired",
}

export class Coupon {
  public id: string
  public tenantId: string
  public storeId: string
  public code: string
  public name: string
  public status: CouponStatus
  public type: CouponType
  public discountAmount: number
  public discountPercent: number
  public discountMinAmount: number
  public discountMaxAmount: number
  public issuingCount: number
  public usedCount: number
  public receivedCount: number
  public minAmount: number
  public maxAmount: number
  public startTime?: string | any
  public endTime?: string | any
  public description: string
}

export class TakeCoupon {
  public id: string
  public tenantId: string
  public storeId: string
  public couponId: string
  public customerId: string
  public code: string
  public name: string
  public amount: number
  public percentage: number
}

export class TakeCouponQuery {
  private params = {}

  public page(page: number) {
    this.params["page"] = page
    return this
  }

  public limit(limit: number) {
    this.params["limit"] = limit
    return this
  }

  public customerId(customerId?: string): TakeCouponQuery {
    if (customerId) {
      this.params["customer_id"] = customerId
    } else {
      _.unset(this.params, "customer_id")
    }
    return this
  }

  public list(): Promise<PageList<TakeCoupon>> {
    return httpClient
      .get(`/v1/customers/coupons`, { params: this.params })
      .then(({ data }) => data)
      .then(camelCase)
      .then(data => {
        return _.assign(PageList.empty(), data, {
          elements: _.map(data.elements, coupons => _.assign(new TakeCoupon(), coupons)),
        })
      })
  }
}


export class CouponQuery {
  private params = {}

  public page(page?: number | string) {
    this.params["page"] = page
    return this
  }

  public limit(limit?: number | string) {
    this.params["limit"] = limit
    return this
  }

  public storeId(storeId: string) {
    this.params["store_id"] = storeId
    return this
  }

  public name(name: string) {
    this.params["name"] = name
    return this
  }

  public types(types?: string | string[]) {
    this.params["types"] = types
    return this
  }

  public statuses(statuses?: string | string[]) {
    this.params["statuses"] = statuses
    return this
  }

  public list(): Promise<PageList<Coupon>> {
    return httpClient
      .get(`/v1/coupons`, { params: this.params })
      .then(({ data }) => data)
      .then(camelCase)
      .then(data => {
        return _.assign(PageList.empty(), data, {
          elements: _.map(data.elements, coupon => _.assign(new Coupon(), coupon)),
        })
      })
  }
}

export class CouponServiceV1 {

  public static createCouponQuery(): CouponQuery {
    return new CouponQuery()
  }

  public static createTakeCouponQuery(): TakeCouponQuery {
    return new TakeCouponQuery()
  }

  public static addCoupon(coupon: Coupon): Promise<Coupon> {
    return httpClient.post("/v1/coupons", snakeCase(coupon))
      .then(({ data }) => data)
      .then(camelCase)
      .then(data => _.assign(new Coupon(), data))
  }

  public static getCoupon(couponId: string): Promise<Coupon> {
    return httpClient.get(`/v1/coupons/${couponId}`)
      .then(({ data }) => data)
      .then(camelCase)
      .then(data => _.assign(new Coupon(), data))
  }

  public static updateCoupon(coupon: Coupon): Promise<Coupon> {
    return httpClient.patch(`/v1/coupons/${coupon.id}`, snakeCase(coupon))
      .then(({ data }) => data)
      .then(camelCase)
      .then(data => _.assign(new Coupon(), data))
  }

  public static pauseCoupon(couponId: string): Promise<void> {
    return httpClient.patch(`/v1/coupons/${couponId}/pause`)
      .then(({ data }) => data)
  }

  public static deleteCoupon(couponId: string): Promise<void> {
    return httpClient.delete(`/v1/coupons/${couponId}`)
      .then(({ data }) => data)
  }
}
